package org.aeon.gamechatnest.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.aeon.gamechatnest.common.response.RespStatus;
import org.aeon.gamechatnest.common.response.ResultBuild;
import org.aeon.gamechatnest.dto.PrivateLetterDto;
import org.aeon.gamechatnest.exception.ApplicationException;
import org.aeon.gamechatnest.mapper.PrivateLetterMapper;
import org.aeon.gamechatnest.pojo.PrivateLetter;
import org.aeon.gamechatnest.service.PrivateLetterService;
import org.aeon.gamechatnest.service.UserService;
import org.aeon.gamechatnest.util.ApplicationAssert;
import org.aeon.gamechatnest.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 私信对话服务（个人对个人）
 *
 * @author : Qik 2024/5/11 17:42
 */
@Service
public class PrivateLetterServiceImpl extends ServiceImpl<PrivateLetterMapper, PrivateLetter> implements PrivateLetterService {
    @Autowired
    private PrivateLetterMapper privateLetterMapper;

    @Autowired
    private UserService userService;

    @Override
    @Transactional(rollbackFor = ApplicationException.class)
    public boolean create(Long toUserId) {
        // 获取登录用户
        Long loginUserId = SecurityUtil.getUserId();

        // 不能和自己创建对话
        if (loginUserId.equals(toUserId)) {
            ResultBuild.result().state(RespStatus.PARAM_ERROR).message("不能和自己创建对话");
            return false;
        }
        // 校验目标用户是否存在
        if (!userService.isExist(toUserId)) {
            ResultBuild.result().state(RespStatus.NOT_FOUND).message("用户不存在，无法创建对话");
            return false;
        }
        // 对话已存在
        PrivateLetter byBothSides = privateLetterMapper.getByBothSides(loginUserId, toUserId);
        if (byBothSides != null) {
            Long privateId = byBothSides.getPrivateId();
            // 根据当前登录用户id来设置对应的对话可见性
            if (loginUserId.equals(byBothSides.getFromUser()) && byBothSides.getFromUserShow() == 1) {
                // 如果登录用户为发送用户，且可见性为隐藏，则更新为显示
                ApplicationAssert.isSuccess(
                        privateLetterMapper.updateFromUserShow(privateId, 0) == 1,
                        new ApplicationException(RespStatus.FAIL, "系统错误，恢复显示对话失败，请联系管理员")
                );
            } else if (loginUserId.equals(byBothSides.getToUser()) && byBothSides.getToUserShow() == 1) {
                // 如果登录用户为接收用户，且可见性为隐藏，则更新为显示
                ApplicationAssert.isSuccess(
                        privateLetterMapper.updateToUserShow(privateId, 0) == 1,
                        new ApplicationException(RespStatus.FAIL, "系统错误，恢复显示对话失败，请联系管理员")
                );
            }
            ResultBuild.result().message("对话已存在，已恢复显示");
            return true;
        }

        // 不存在再新建私信对话
        PrivateLetter privateLetter = new PrivateLetter();
        privateLetter.setFromUser(loginUserId);
        privateLetter.setToUser(toUserId);
        privateLetter.setCreateTime(new Date());
        privateLetter.setFromUserShow(0);
        privateLetter.setToUserShow(0);
        privateLetter.setIsDelete(0);

        // 执行新增
        ApplicationAssert.isSuccess(
                privateLetterMapper.add(privateLetter) == 1,
                new ApplicationException(RespStatus.FAIL, "系统错误，建立对话失败，请联系管理员")
        );
        return true;
    }

    @Override
    public boolean hide(Long privateId) {
        // 获取登录用户
        Long loginUserId = SecurityUtil.getUserId();

        // 对话不存在
        PrivateLetter privateLetter = privateLetterMapper.getById(privateId);
        if (privateLetter == null) {
            ResultBuild.result().state(RespStatus.NOT_FOUND).message("对话不存在");
            return false;
        }
        // 对话不是当前用户的（既不是发送用户，也不是接收用户）
        if (!loginUserId.equals(privateLetter.getFromUser()) && !loginUserId.equals(privateLetter.getToUser())) {
            ResultBuild.result().state(RespStatus.NO_PERMISSION).message("对话不属于当前用户");
            return false;
        }

        // 根据登录用户是发送发还是接收方，更新可见状态为1：隐藏
        if (loginUserId.equals(privateLetter.getFromUser()) && privateLetter.getFromUserShow() == 0) {
            // 登录用户为发送方，且发送发显示为0：显示状态
            ApplicationAssert.isSuccess(
                    privateLetterMapper.updateFromUserShow(privateId, 1) == 1,
                    new ApplicationException(RespStatus.FAIL, "系统错误，隐藏对话失败，请联系管理员")
            );
        } else if (loginUserId.equals(privateLetter.getToUser()) && privateLetter.getToUserShow() == 0) {
            // 登录用户为接收方，且接收方显示为0：显示状态
            ApplicationAssert.isSuccess(
                    privateLetterMapper.updateToUserShow(privateId, 1) == 1,
                    new ApplicationException(RespStatus.FAIL, "系统错误，隐藏对话失败，请联系管理员")
            );
        }

        return true;
    }

    @Override
    public PrivateLetter findById(Long privateId) {
        PrivateLetter privateLetter = privateLetterMapper.getById(privateId);
        ApplicationAssert.nonNull(privateLetter);
        return privateLetter;
    }

    @Override
    public List<Long> findIdByUserId(Long userId) {
        return privateLetterMapper.getIdsByUserId(userId);
    }

    @Override
    public List<PrivateLetterDto> getPrivateMessageUsers(Long userId) {
        // 查找用户id为userId的私信列表
        List<PrivateLetter> privateLetters = privateLetterMapper.findByUserId(userId);
        // 将私信列表转换为私信DTO列表
        return privateLetters.stream().map(privateLetter -> {
            // 创建私信DTO实例
            PrivateLetterDto privateLetterDto = new PrivateLetterDto();
            // 设置私信id
            privateLetterDto.setPrivateId(privateLetter.getPrivateId());
            // 查找对方用户的信息
            if (Objects.equals(privateLetter.getToUser(), userId)) {
                privateLetterDto.setTargetUser(userService.findVo(privateLetter.getFromUser()));
            } else {
                privateLetterDto.setTargetUser(userService.findVo(privateLetter.getToUser()));
            }
            // 返回私信DTO实例
            return privateLetterDto;
        }).toList();
    }
}
